package cn.demomaster.quickrouter.lifecycle

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.Path
import android.os.Handler
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.ScaleGestureDetector.OnScaleGestureListener
import android.view.View
import android.view.ViewGroup
import androidx.customview.widget.ViewDragHelper
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sqrt


class LifecycleTimelineView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private var mScaleGestureDetector: ScaleGestureDetector? = null
    private var mDragHelper: ViewDragHelper? = null
    init {
//        mScaleGestureDetector = ScaleGestureDetector(
//            context,
//            ScaleGestureListener()
//        )
//        mDragHelper =
//            ViewDragHelper.create((parent as ViewGroup)!!, 1.0f, DragHelperCallback())
    }

    private val traces = mutableListOf<LifecycleTrace>()
    private var scaleFactor = 1.0f
    private var translateX = 0f
    private var translateY = 0f

    private val axisPaint = Paint().apply {
        color = Color.GRAY
        strokeWidth = 2f
        pathEffect = DashPathEffect(floatArrayOf(10f, 5f), 0f)
    }

    private val eventPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.FILL
    }

    private val textPaint = Paint().apply {
        color = Color.BLACK
        textSize = 24f
    }

    private val traceTextPaint = Paint().apply {
        color = Color.RED
        textSize = 24f
    }

    private val linePaint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 5f
        color = Color.GREEN
    }
    private val pointRadius = 12
    private val pointPaint = Paint().apply {
        style = Paint.Style.FILL
        color = Color.CYAN
    }

    private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onScroll(
            e1: MotionEvent?,
            e2: MotionEvent,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            translateX -= distanceX / scaleFactor
            translateY -= distanceY / scaleFactor
            offsetX = translateX
            offsetY = translateY
            invalidate()
            return true
        }
    })

    private val scaleGestureListener = ScaleGestureDetector(context, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            scaleFactor *= detector.scaleFactor
            return super.onScale(detector)
        }
    })

    override fun onTouchEvent(event: MotionEvent): Boolean {
        var pointerCount = event.pointerCount
        if(pointerCount>1){
            scaleGestureListener.onTouchEvent(event)
        }
        gestureDetector.onTouchEvent(event)
        return true
    }

    fun addTrace(trace: LifecycleTrace) {
        traces.add(trace)
        invalidate()
    }
    fun addTrace(LifecycleTraces: MutableList<LifecycleTrace>) {
        traces.addAll(LifecycleTraces)
        invalidate()
    }
    var totalTime = 0L;
    var leftTime = 0L;
    var rightTime = 0;
    override fun onDraw(canvas: Canvas) {
        canvas.save()
        canvas.scale(scaleFactor, scaleFactor)
        //canvas.translate(translateX, translateY)
        if(traces.size>=2) {
            leftTime = traces.get(0).createTime;
            totalTime = traces.get(traces.size - 1).lastTime - leftTime;

            //drawTimeAxis(canvas)
            drawTraces(canvas)
        }
        canvas.restore()
    }

    private fun drawTimeAxis(canvas: Canvas) {
        val centerY = height / 2f
        canvas.drawLine(50f, centerY, width - 50f, centerY, axisPaint)
    }

    private fun drawTraces(canvas: Canvas) {
        var yPos = 100f
        traces.forEach { trace ->
            drawTrace(canvas, trace, yPos+offsetY)
            yPos += 100f
        }
    }

    private fun drawTrace(canvas: Canvas, trace: LifecycleTrace, yPos: Float) {
        // 具体绘制实现
        var lineWidth = width*5;
        var path: Path? = null
        for ((i,event) in trace.lifecycleEvents.withIndex()) {

            var x = ((event.createTime - leftTime).toFloat() / totalTime.toFloat() * lineWidth)+offsetX
            if (path == null) {
                path = Path()
                path.moveTo(x , yPos)
            } else {
                path.lineTo(x , yPos)
            }
            //System.out.println("time="+lifeCycleEvent.time+",widthX="+widthX+",x=" + x);
            canvas.drawCircle(x, yPos, pointRadius.toFloat(), pointPaint)
            var lableY = yPos - pointRadius.toFloat() - 5;
            if(i==0){
                //绘制虚线
                canvas.drawLine(0f, yPos, lineWidth.toFloat(), yPos, axisPaint)
                canvas.drawText(trace.traceName, x, lableY-traceTextPaint.textSize, traceTextPaint)
            }
            canvas.drawText(event.lifecycleType.toString(), x, lableY, textPaint)
        }
        //path.close();
        canvas.drawPath(path!!, linePaint)

    }

    private var offsetX = 0f //x轴偏移量
    private var offsetY = 0f //y轴偏移量
    private var scaleType = ScaleType.scaleX
    private var transitionType = TransitionType.horizontal

    fun setScaleType(scaleType: ScaleType) {
        this.scaleType = scaleType
        postInvalidate()
    }

    fun setTransitionType(transitionType: TransitionType) {
        this.transitionType = transitionType
        offsetX = 0f
        offsetY = 0f
        postInvalidate()
    }

    enum class ScaleType {
        scaleX,  //x轴缩放
        scaleY,  //y轴缩放
        scaleXY,  //xy轴都缩放
        none //不允许缩放
    }

    /**
     * 移动类型
     */
    enum class TransitionType {
        horizontal,  //横向滚动
        vertical,  //纵向滚动
        transitionXY,  //任意移动
        none //不允许移动
    }

    private val handler = Handler()

    private var lastMultiTouchTime: Long = 0 // 记录多点触控缩放后的时间
    private var preScale = 1f // 默认前一次缩放比例为1
    private var scale = 1f

    /**
     * 控制缩放
     */
    /*class ScaleGestureListener : OnScaleGestureListener {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            val previousSpan =
                max(1.0, detector.previousSpan.toDouble()).toFloat() // 前一次双指间距
            val currentSpan = detector.currentSpan // 本次双指间距
            if (currentSpan < previousSpan) {
                // 缩小
                scale = max(
                    (preScale * abs((currentSpan / previousSpan).toDouble())).toDouble(),
                    0.01
                ) //最小0.1倍数
                Log.i(LifecycleView.TAG, "缩小:$scale")
            } else {
                // 放大
                scale = min(
                    (preScale * abs((currentSpan / previousSpan).toDouble())).toDouble(),
                    50.0
                ) //最大50倍数
                Log.i(LifecycleView.TAG, "放大:$scale")
            }
            invalidate()
            return false
        }

        override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
            // 一定要返回true才会进入onScale()这个函数
            return true
        }

        override fun onScaleEnd(detector: ScaleGestureDetector) {
            preScale = scale // 记录本次缩放比例
            lastMultiTouchTime = System.currentTimeMillis() // 记录双指缩放后的时间
        }
    }


    *//**
     * 控制位移
     *//*
    class DragHelperCallback : ViewDragHelper.Callback() {
        //这个地方实际上函数返回值为true就代表可以滑动 为false 则不能滑动
        override fun tryCaptureView(child: View, pointerId: Int): Boolean {
            return child === this@LifecycleTimelineView
        }

        override fun onViewPositionChanged(
            changedView: View,
            left: Int,
            top: Int,
            dx: Int,
            dy: Int
        ) {
            Log.i(LifecycleView.TAG, "onViewPositionChanged")
        }

        override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
            Log.i(LifecycleView.TAG, "onViewReleased,xvel=$xvel,yvel=$yvel")
            //int top = getPaddingTop();
            // mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);
            //mScroller.startScroll;
            if (transitionType != LifecycleView.TransitionType.none) {
                fling(xvel.toInt(), yvel.toInt())
            }
        }

        override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
            Log.i(LifecycleView.TAG, "clampViewPositionHorizontal,left=$left,dx=$dx")
            if (transitionType != LifecycleView.TransitionType.vertical && transitionType != LifecycleView.TransitionType.none) {
                offsetX = offsetX + dx
                postInvalidate()
            }
            return 0
        }

        override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
            Log.i(LifecycleView.TAG, "clampViewPositionVertical,top=$top,dy=$dy")
            if (transitionType != LifecycleView.TransitionType.horizontal && transitionType != LifecycleView.TransitionType.none) {
                offsetY = offsetY + dy
                postInvalidate()
            }
            return getTop()
        }
    }

    var dx: Int = 0
    var dy: Int = 0

    private fun fling(xvel: Int, yvel: Int) {
        dx = sqrt(xvel.toDouble()).toInt()
        dy = sqrt(yvel.toDouble()).toInt()
        if (transitionType == LifecycleView.TransitionType.horizontal || transitionType == LifecycleView.TransitionType.transitionXY) {
            if (dx < 0) {
                (offsetX += max(dx.toDouble(), -200.0)).toFloat()
            } else {
                (offsetX += min(dx.toDouble(), 200.0)).toFloat()
            }
        }
        if (transitionType == LifecycleView.TransitionType.vertical || transitionType == LifecycleView.TransitionType.transitionXY) {
            if (dy < 0) {
                (offsetY += max(dy.toDouble(), -200.0)).toFloat()
            } else {
                (offsetY += min(dy.toDouble(), 200.0)).toFloat()
            }
        }
        postInvalidate()
        val t = (if (transitionType == LifecycleView.TransitionType.horizontal) dx else dy)
        if (abs(t.toDouble()) > 2) {
            handler.postDelayed({ fling(dx, dy) }, 10)
        }
    }*/
}
